/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using EnvDTE;
using VSLangProj80;
using DaveSexton.DocProject.Engine;
using DaveSexton.DocProject.Configuration;
using EnvDTE80;

namespace DaveSexton.DocProject.Options
{
	public sealed partial class ProjectOptions : OptionsDialogBase
	{
		#region Public Properties
		#endregion

		#region Private / Protected
		private readonly KeyedProjectCollection<IDocProject> docProjects = new KeyedProjectCollection<IDocProject>();
		private readonly Dictionary<IDocProject, bool> projectsBufferUsage = new Dictionary<IDocProject, bool>();
		private readonly ServiceContainer serviceContainer = new ServiceContainer();
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="ProjectOptions" /> class.
		/// </summary>
		public ProjectOptions()
		{
			InitializeComponent();
		}
		#endregion

		#region Methods
		[CLSCompliant(false)]
		protected override void Initialize(DTE dte)
		{
			docProjects.Clear();
			projectsComboBox.Items.Clear();

			foreach (IDocProject project in DocProjectEnvironment.FindProjects(
				delegate(IAnyProject currentProject) { return currentProject is IDocProject; }))
			{
				// NOTE: save the project so that previously committed, yet unsaved changes are not lost if the dialog is canceled.
				// (This only applies to "custom" options that are only implemented using a single buffer approach.)
				project.Save();

				docProjects.Add(project);
				projectsBufferUsage[project] = project.Settings.UseBuffer;

				project.Settings.UseBuffer = true;

				projectsComboBox.Items.Add(KeyedProjectCollection<IDocProject>.CreateKeyedProjectItem(project));

				// required so that the grid can find services such as IComponentChangeService
				serviceContainer.Add(project.Options);
			}

			if (docProjects.Count == 0)
				EnableUI(false);
			else
			{
				projectsComboBox.SelectedIndex = 0;
				EnableUI(true);
			}
		}

		private void EnableUI(bool enabled)
		{
			propertyGrid.Visible = enabled;
			projectsComboBox.Visible = enabled;
			nothingToConfigureLabel.Visible = !enabled;
		}

		protected override void OnOk()
		{
			foreach (IDocProject project in docProjects)
			{
				if (project.Settings.CanCommit)
					project.Settings.Commit();

				project.Settings.UseBuffer = projectsBufferUsage[project];

				project.Options.Commit();
			}
		}

		protected override void OnCancel()
		{
			foreach (IDocProject project in docProjects)
			{
				project.Settings.Clear();
				project.Settings.UseBuffer = projectsBufferUsage[project];

				project.Options.Cancel();
			}
		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (components != null)
					components.Dispose();

				serviceContainer.Dispose();
			}
			base.Dispose(disposing);
		}
		#endregion

		#region Event Handlers
		protected override void OnLoad(EventArgs e)
		{
			if (Site == null || !Site.DesignMode)
				// required so that the grid can find services such as IComponentChangeService
				serviceContainer.Add(propertyGrid);

			base.OnLoad(e);
		}

		private void projectsComboBox_SelectedIndexChanged(object sender, EventArgs e)
		{
			KeyedProjectItem item = (KeyedProjectItem) projectsComboBox.SelectedItem;

			if (docProjects.Contains(item.Key))
				propertyGrid.SelectedObject = docProjects[item.Key].Options;
			else
				propertyGrid.SelectedObject = null;
    }

    // NOTE: A Reset/Description context menu strip cannot be used because of mouse captures issues
    // while the control is being hosted by an ActiveX control (the VS options page shim).
    // The following behavior was observed in both VS 2005 and VS 2008 Beta 2: 
    // 1. When the menu is opened it remains open until an enabled item is clicked.
    // 2. Explicitly assinging mouse capture to the menu (contextMenu.Capture = true) while executing
    //    an event handler for the Opening event fixes the problem and the menu behaves normally.
    // 3. But by capturing the mouse there are problems throughout VS with all of its menu strips once 
    //    the options dialog is closed.  The next action performed by the user on any of VS's context 
    //    menus or its main menu has a high chance of crashing VS.  In most cases, once a context menu 
    //    as opened it remains opened in VS even after the user clicks outside of its visible region 
    //    (as if the menu couldn't acquire mouse capture on its own when it opened).
    // 4. Even if Capture is set to false in the menu's Closing event (verified to execute by attaching 
    //    a debugger) the issues in #3 with VS's menus not closing and sometimes VS crashing, still exist.
		#endregion
	}
}
